/**
 * 
 */
package org.yelongframework.freemarker;

import java.util.HashMap;
import java.util.Objects;

import org.yelongframework.lang.Nullable;
import org.yelongframework.ognl.OgnlWrapper;

/**
 * 实体映射。用于存储实体对象。可以设置属性获取时的默认值，防止freemarker解析错误问题
 * 
 * @param <T> entity type
 * @since 1.0.0
 */
public class EntityMap<T> extends HashMap<String, Object> {// 必须继承 HashMap，且clone返回本身

	private static final long serialVersionUID = -1313237965432896603L;

	/** 默认值 */
	public static final String DEFAULT_VALUE = "";

	/** 包装的实体 */
	@Nullable
	private T entity;

	/** 默认值 */
	@Nullable
	private String defaultValue = DEFAULT_VALUE;

	/** OGNL包装器 */
	private OgnlWrapper ognlWrapper = new OgnlWrapper();

	// ==================================================构造器==================================================

	public EntityMap() {
	}

	/**
	 * @param entity 包装的实体
	 */
	public EntityMap(@Nullable T entity) {
		setEntity(entity);
	}

	// ==================================================获取==================================================

	@Override
	public Object get(Object key) {
		Object value = super.get(key);
		if (null == value) {
			value = ognlWrapper.getValue(key.toString());
		}
		return value != null ? value : defaultValue;
	}

	// ==================================================添加==================================================

	@Override
	public Object put(String key, Object value) {
		// 如果设置的值与 entity 中属性冲突，已 put 值为准
		return super.put(key, value);
	}

	// ==================================================默认值==================================================

	/**
	 * @return 默认值
	 */
	public String getDefaultValue() {
		return defaultValue;
	}

	/**
	 * 设置默认值
	 * 
	 * @param defaultValue 默认值
	 * @return this
	 */
	public EntityMap<T> setDefaultValue(@Nullable String defaultValue) {
		this.defaultValue = defaultValue;
		return this;
	}

	// ==================================================OGNL包装器==================================================

	/**
	 * @return OGNL包装器
	 */
	public OgnlWrapper getOgnlWrapper() {
		return ognlWrapper;
	}

	/**
	 * 设置OGNL包装器
	 * 
	 * @param ognlWrapper OGNL包装器
	 */
	public void setOgnlWrapper(OgnlWrapper ognlWrapper) {
		this.ognlWrapper = Objects.requireNonNull(ognlWrapper, "ognlWrapper");
	}

	// ==================================================实体==================================================

	/**
	 * @return 包装的实体
	 */
	@Nullable
	public T getEntity() {
		return entity;
	}

	/**
	 * @param entity 包装的实体
	 */
	public void setEntity(T entity) {
		this.entity = entity;
		if (null != entity) {
			ognlWrapper.setRoot(entity);
		}
	}

	// ==================================================实现==================================================

	@Override
	public Object clone() {
		// freemarker 会调用 HashMap 的 clone 方法。这里直接返回自己
		return this;
	}

}
